import { useDrag, useDrop } from 'react-dnd';

import type {
  Column,
  ColumnOrderState,
  Header,
  Row,
  Table,
} from '@tanstack/react-table';
import type { AnyObject } from '../type';

const reorderColumn = (
  draggedColumnId: string,
  targetColumnId: string,
  columnOrder: string[],
): ColumnOrderState => {
  columnOrder.splice(
    columnOrder.indexOf(targetColumnId),
    0,
    columnOrder.splice(columnOrder.indexOf(draggedColumnId), 1)[0] as string,
  );
  return [...columnOrder];
};

export function useDraggableColumn<T extends AnyObject>({
  header,
  table,
}: {
  header: Header<T, unknown>;
  table: Table<T>;
}) {
  const { getState, setColumnOrder } = table;
  const { columnOrder } = getState();
  const { column } = header;

  const [, dropRef] = useDrop({
    accept: 'column',
    drop: (draggedColumn: Column<T>) => {
      const newColumnOrder = reorderColumn(
        draggedColumn.id,
        column.id,
        columnOrder,
      );

      setColumnOrder(newColumnOrder);
    },
  });

  const [{ isDragging }, dragRef, previewRef] = useDrag({
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
    item: () => column,
    type: 'column',
  });
  return { dropRef, dragRef, previewRef, isDragging };
}

export function useDraggableRow<T extends AnyObject>({
  row,
  reorderRow,
}: {
  row: Row<T>;
  reorderRow: (draggedRowIndex: number, targetRowIndex: number) => void;
}) {
  const [, dropRef] = useDrop({
    accept: 'row',
    drop: (draggedRow: Row<T>) => reorderRow(draggedRow.index, row.index),
  });

  const [{ isDragging }, dragRef, previewRef] = useDrag({
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
    item: () => row,
    type: 'row',
  });
  return { dropRef, dragRef, previewRef, isDragging };
}
